
#include "gdisp_lld_hal.h"

typedef enum {RECEIVE, TRANSMIT, UNDEFINED} state_IO;
static volatile state_IO state_tr;

static void gdisp_lld_all_DB_pin_in(void);
static void gdisp_lld_all_DB_pin_out(void);

/*
 * You must implement the init_board routine for your board.
 */
void gdisp_lld_init_board(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(	LCD_GPIO_CLK_DB0_DB7	|
							LCD_GPIO_CLK_DB8_DB15	|
							LCD_GPIO_CLK_BL			|
							LCD_GPIO_CLK_WR			|
							LCD_GPIO_CLK_CS			|
							LCD_GPIO_CLK_RS			|
							LCD_GPIO_CLK_RD, ENABLE);

	/* For all pins. */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

	/* BL pin. */
	GPIO_InitStructure.GPIO_Pin = LCD_GPIO_Pin_BL;
	GPIO_Init(LCD_GPIO_PORT_BL, &GPIO_InitStructure);

	/* WR pin. */
	GPIO_InitStructure.GPIO_Pin = LCD_GPIO_Pin_WR;
	GPIO_Init(LCD_GPIO_PORT_WR, &GPIO_InitStructure);

	/* CS pin. */
	GPIO_InitStructure.GPIO_Pin = LCD_GPIO_Pin_CS;
	GPIO_Init(LCD_GPIO_PORT_CS, &GPIO_InitStructure);

	/* RS pin. */
	GPIO_InitStructure.GPIO_Pin = LCD_GPIO_Pin_RS;
	GPIO_Init(LCD_GPIO_PORT_RS, &GPIO_InitStructure);

	/* RD pin. */
	GPIO_InitStructure.GPIO_Pin = LCD_GPIO_Pin_RD;
	GPIO_Init(LCD_GPIO_PORT_RD, &GPIO_InitStructure);

	GDISP_LLD_CHIP_SELECT_DISABLE;
	GDISP_LLD_REGISTER_SELECT_DISABLE;
	GDISP_LLD_READ_STROBE_DISABLE;
	GDISP_LLD_WRITE_STROBE_DISABLE;

	state_tr = UNDEFINED;
}

/**
  * All gpio data(DB15-DB0) pin output.
  */
static void gdisp_lld_all_DB_pin_out(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* Configuration DB15-DB0 pins. */
	GPIO_InitStructure.GPIO_Pin =(	LCD_GPIO_Pin_DB_0	|
									LCD_GPIO_Pin_DB_1	|
									LCD_GPIO_Pin_DB_2	|
									LCD_GPIO_Pin_DB_3	|
									LCD_GPIO_Pin_DB_4	|
									LCD_GPIO_Pin_DB_5	|
									LCD_GPIO_Pin_DB_6	|
									LCD_GPIO_Pin_DB_7	);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(LCD_GPIO_PORT_DB0_DB7, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin =(	LCD_GPIO_Pin_DB_8	|
									LCD_GPIO_Pin_DB_9	|
									LCD_GPIO_Pin_DB_10	|
									LCD_GPIO_Pin_DB_11	|
									LCD_GPIO_Pin_DB_12	|
									LCD_GPIO_Pin_DB_13	|
									LCD_GPIO_Pin_DB_14	|
									LCD_GPIO_Pin_DB_15	);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * All gpio data(DB15-DB0) pin input.
  */
static void gdisp_lld_all_DB_pin_in(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* Configuration DB15-DB0 pins. */
	GPIO_InitStructure.GPIO_Pin =(	LCD_GPIO_Pin_DB_0	|
									LCD_GPIO_Pin_DB_1	|
									LCD_GPIO_Pin_DB_2	|
									LCD_GPIO_Pin_DB_3	|
									LCD_GPIO_Pin_DB_4	|
									LCD_GPIO_Pin_DB_5	|
									LCD_GPIO_Pin_DB_6	|
									LCD_GPIO_Pin_DB_7	);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(LCD_GPIO_PORT_DB0_DB7, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin =(	LCD_GPIO_Pin_DB_8	|
									LCD_GPIO_Pin_DB_9	|
									LCD_GPIO_Pin_DB_10	|
									LCD_GPIO_Pin_DB_11	|
									LCD_GPIO_Pin_DB_12	|
									LCD_GPIO_Pin_DB_13	|
									LCD_GPIO_Pin_DB_14	|
									LCD_GPIO_Pin_DB_15	);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * You must implement write_index routine for your board.
  */
void gdisp_lld_write_index(uint16_t data)
{
	if(state_tr == UNDEFINED || state_tr == RECEIVE)
	{
		gdisp_lld_all_DB_pin_out();
		state_tr = TRANSMIT;
	}

	GDISP_LLD_CHIP_SELECT_ENABLE;
	GDISP_LLD_REGISTER_SELECT_ENABLE;

	/* Strobe the WR write line (data is latched on the rising-edge) */
	GDISP_LLD_WRITE_STROBE_ENABLE;
	GDISP_LCD_WRITE(data);
	GDISP_LLD_WRITE_STROBE_DISABLE;

	GDISP_LLD_CHIP_SELECT_DISABLE;
	GDISP_LLD_REGISTER_SELECT_DISABLE;
}

/**
  * You must implement write_data routine for your board.
  */
void gdisp_lld_write_data(uint16_t data)
{
	if(state_tr == UNDEFINED || state_tr == RECEIVE)
	{
		gdisp_lld_all_DB_pin_out();
		state_tr = TRANSMIT;
	}

	GDISP_LLD_CHIP_SELECT_ENABLE;
	//GDISP_LLD_REGISTER_SELECT_DISABLE;

	/* Strobe the WR write line (data is latched on the rising-edge) */
	GDISP_LLD_WRITE_STROBE_ENABLE;
	GDISP_LCD_WRITE(data);
	GDISP_LLD_WRITE_STROBE_DISABLE;

	GDISP_LLD_CHIP_SELECT_DISABLE;
}

/**
  * You must implement read_data routine for your board.
  */
uint16_t gdisp_lld_read_data(void)
{
	uint16_t data;

	if(state_tr == UNDEFINED || state_tr == TRANSMIT)
	{
		gdisp_lld_all_DB_pin_in();
		state_tr = RECEIVE;
	}

	GDISP_LLD_CHIP_SELECT_ENABLE;
	//GDISP_LLD_REGISTER_SELECT_DISABLE;

	/* Strobe the RD read line (data is latched on the rising-edge) */
	GDISP_LLD_READ_STROBE_ENABLE;
	data = (uint16_t)GDISP_LCD_READ();
	GDISP_LLD_READ_STROBE_DISABLE;

	GDISP_LLD_CHIP_SELECT_DISABLE;

	return data;
}

/**
  * You must implement set_backlight routine for your board.
  */
void gdisp_lld_backlight(uint8_t percentage)
{
	if(percentage)
	{
		GPIO_SetBits(LCD_GPIO_PORT_BL, LCD_GPIO_Pin_BL);
	}
	else
	{
		GPIO_ResetBits(LCD_GPIO_PORT_BL, LCD_GPIO_Pin_BL);
	}
}

/**
  * You must implement setpin_reset routine for your board.
  */
void acquire_bus(void)
{
	/* Nothing to do here since LCD is the only device on that bus */
}

/**
  * You must implement setpin_reset routine for your board.
  */
void release_bus(void)
{
	/* Nothing to do here since LCD is the only device on that bus */
}

/**
  * You must implement setpin_reset routine for your board.
  */
void gdisp_lld_reset_pin(bool state)
{
	/* Does nothing since reset_pin connected to the reset button. */
	/* See circuitry board. */
}
